<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/31
 * Time: 9:44
 */

namespace app\api\service;


use app\api\model\User as userModel;
use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;

class UserToken extends ToToken
{
    protected $code;
    protected $wxAppId;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code=$code;
        $this->wxAppId=config("wx.app_id");
        $this->wxAppSecret=config("wx.secret");
        $this->wxLoginUrl=sprintf(config("wx.login_url"),
            $this->wxAppId,$this->wxAppSecret,$this->code);
    }


    /**
     * 登陆
     * 思路1：每次调用登录接口都去微信刷新一次session_key，生成新的Token，不删除久的Token
     * 思路2：检查Token有没有过期，没有过期则直接返回当前Token
     * 思路3：重新去微信刷新session_key并删除当前Token，返回新的Token
     */
    public function get(){
        $result = curl_get($this->wxLoginUrl);

        // 注意json_decode的第一个参数true
        // 这将使字符串被转化为数组而非对象
        $wxResult = json_decode($result,true);
        if (empty($wxResult)){
            throw new Exception("获取session_key及oppenid时异常,微信内部错误");
        }else{
            $loginFail = array_key_exists('errcode',$wxResult);
            if ($loginFail){
                $this->processLoginError($wxResult);
            }else{
                return  $this->grantToken($wxResult);
            }
        }
    }

    private function grantToken($wxResult){
        //把令牌返回客户端
        //拿到oppenid
        $openid = $wxResult['openid'];
        //数据库查看,这个openid是否存在
        $user = userModel::getByOpenId($openid);
        if ($user){
            $uid = $user->id;
        }else{
            //存在,则不处理.不存在,则新增一条记录
            $uid = $this->newUser($openid);
        }
        //生成令牌,准备缓存数据,写入缓存
        //key:令牌
        //value:wxResult,uid,scope(权限)
        $cachedValue = $this->prepareCachedValue($wxResult,$uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }

    private function saveToCache($cachedValue){
        $key = self::generateToken();
        $value = json_encode($cachedValue);
        $expire_in = config('setting.token_expire_in');

        //写入缓存
        $request = cache($key,$value,$expire_in);
        if (!$request){
            throw new TokenException([
                'msg'=>'服务器异常',
                'errorCode'=>10005,
            ]);
        }
        return $key;
    }

    //准备缓存的数据
    private function prepareCachedValue($wxResult,$uid){
        $cachedValue = $wxResult;
        $cachedValue['uid']=$uid;

//        $cachedValue['scope']=16;//代表用户的权限数值
//        $cachedValue['scope']=32;//代表CMS(管理员)用户的权限数值
        $cachedValue['scope'] = ScopeEnum::User;

        return $cachedValue;
    }

    //创建新用户
    private function newUser($openid){
        $user = userModel::create([
            'openid'=>$openid,
        ]);
        return $user->id;
    }

    // 处理微信登陆异常
    // 那些异常应该返回客户端，那些异常不应该返回客户端
    // 需要认真思考
    private function processLoginError($wxResult)
    {
        throw new WeChatException([
                'msg' => $wxResult['errmsg'],
                'errorCode' => $wxResult['errcode']
            ]);
    }
}